package com.ds.infrastructure.audit.collector.interceptor;

import com.ds.infrastructure.audit.collector.config.SSOConfig;
import com.ds.infrastructure.audit.collector.constant.CollectorConstant;
import com.ds.infrastructure.audit.collector.entity.UserInfo;
import com.ds.infrastructure.audit.collector.service.SSOService;
import com.ds.infrastructure.audit.collector.util.RequestUtils;
import com.ds.infrastructure.audit.common.constant.CommonConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.IOException;


/**
 * 作用：
 *
 * @author WeiShaoying
 * @date 2020/8/3
 */
@Order(Ordered.HIGHEST_PRECEDENCE + 2)
@WebFilter(urlPatterns = "/*", filterName = "authenticationFilter",
        initParams = {
                @WebInitParam(name = "exclusions", value = "*.js,*.gif,*.jpg,*.html")
        }
)
@ConditionalOnProperty(name = "sso.enable", havingValue = "true")
@Slf4j
@SuppressWarnings("ALL")
public class AuthenticationFilter implements Filter {

    private static final String STATIC_RESOURCE_REGEX = ".*\\.(js|html|htm|png|css|woff2)$";

    @Autowired
    private SSOService ssoService;

    @Autowired
    private SSOConfig ssoConfig;

    @Override
    public void init(FilterConfig filterConfig) {
        log.debug("init: {}", filterConfig.getInitParameterNames().hasMoreElements());
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        String requestUri = ((HttpServletRequest) request).getRequestURI();
        log.info("Filter url={}", requestUri);
        if (isStaticResource(requestUri) || requestUri.startsWith(CollectorConstant.URL_SSO)) {
            chain.doFilter(request, response);
            return;
        }
        UserInfo userInfo = auth((HttpServletRequest) request);
        if (userInfo != null) {
            chain.doFilter(request, response);
        } else {
            HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper((HttpServletResponse) response);
            wrapper.sendRedirect(ssoConfig.getLoginUrl() + "?service=" + ssoConfig.getService());
        }
    }

    private UserInfo auth(HttpServletRequest request) {
        //从参数中获取
        String sid = RequestUtils.getAuthorization(request);
        if (StringUtils.isNotBlank(sid)) {
            return ssoService.getUserInfo(sid);
        }

        String auth = request.getHeader(CommonConstant.HTTP_HEADER_AUTHORIZATION);
        log.debug("auth: {}", auth);
        if (StringUtils.isEmpty(auth)) {
            Cookie[] cookies = request.getCookies();
            if (cookies == null) {
                return null;
            }
            for (Cookie cookie : cookies) {
                if ("sid".equals(cookie.getName())) {
                    auth = cookie.getValue();
                    break;
                }
            }
        }
        if (StringUtils.isEmpty(auth)) {
            return null;
        }
        return ssoService.getUserInfo(auth);
    }

    private boolean isStaticResource(String uri) {
        return StringUtils.isNotEmpty(uri) && uri.matches(STATIC_RESOURCE_REGEX);
    }

}
